package com.yfp.auth.service;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.core.text.CharSequenceUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import com.github.binarywang.wxpay.bean.result.WxPayUnifiedOrderV3Result;
import com.yfp.auth.form.CaptchaBody;
import com.yfp.auth.form.LoginBody;
import com.yfp.auth.form.ResetPasswordBody;
import com.yfp.auth.form.UserVO;
import com.yfp.common.core.constant.*;
import com.yfp.common.core.domain.R;
import com.yfp.common.core.enums.UserStatus;
import com.yfp.common.core.exception.ServiceException;
import com.yfp.common.core.exception.auth.NotLoginException;
import com.yfp.common.core.text.Convert;
import com.yfp.common.core.utils.AliYunSmsUtils;
import com.yfp.common.core.utils.StringUtils;
import com.yfp.common.core.utils.ip.IpUtils;
import com.yfp.common.core.utils.sign.RsaUtils;
import com.yfp.common.redis.service.RedisService;
import com.yfp.common.security.service.TokenService;
import com.yfp.common.security.utils.SecurityUtils;
import com.yfp.operation.api.RemoteGroupService;
import com.yfp.operation.domain.GroupRegisterBody;
import com.yfp.system.api.RemoteBrowserLoginService;
import com.yfp.system.api.RemoteUserService;
import com.yfp.system.api.domain.SysRole;
import com.yfp.system.api.domain.SysUser;
import com.yfp.system.api.domain.vo.SysRoleVO;
import com.yfp.system.api.model.LoginUser;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import static com.yfp.common.core.constant.Constants.*;

/**
 * 登录校验方法
 *
 *
 */
@Component
@Slf4j
public class SysLoginService {
    @Resource
    AliYunSmsUtils aliYunSmsUtils;
    @Resource
    private RemoteUserService remoteUserService;
    @Resource
    private SysPasswordService passwordService;
    @Resource
    private SysRecordLogService recordLogService;
    @Resource
    private RedisService redisService;
    @Autowired
    CaptchaService createCaptcha;
    @Resource
    private RemoteBrowserLoginService remoteBrowserLoginService;
    @Resource
    private RemoteGroupService remoteGroupService;
    @Resource
    private TokenService tokenService;

    /**
     * 登录
     */
    public LoginUser login(String username, String password) {
        if (!redisService.canSendMessage(username)) throw new ServiceException("账号已锁定,请十分钟后再进行尝试");

        // 用户名或密码为空 错误
        if (CharSequenceUtil.isAllBlank(username, password)) {
            recordLogService.recordLogininfor(username, LOGIN_FAIL, "用户/密码必须填写");
            throw new ServiceException("用户/密码必须填写");
        }
        // 密码如果不在指定范围内 错误
        if (password.length() < UserConstants.PASSWORD_MIN_LENGTH || password.length() > UserConstants.PASSWORD_MAX_LENGTH) {
            if (!redisService.canSendMessage(username)) throw new ServiceException("账号已锁定,请十分钟后再进行尝试");
            recordLogService.recordLogininfor(username, LOGIN_FAIL, "密码错误,登录失败");
            throw new ServiceException("密码错误,登录失败");
        }
        // 用户名不在指定范围内 错误
        if (username.length() != UserConstants.USERNAME_MIN_LENGTH) {
            if (!redisService.canSendMessage(username)) throw new ServiceException("账号已锁定,请十分钟后再进行尝试");
            recordLogService.recordLogininfor(username, LOGIN_FAIL, "用户名不在指定范围(11位)");
            throw new ServiceException("用户名不在指定范围");
        }
        if (!Validator.isMobile(username)) {
            if (!redisService.canSendMessage(username)) throw new ServiceException("账号已锁定,请十分钟后再进行尝试");
            recordLogService.recordLogininfor(username, "Error", "用户名不在指定范围");
            throw new ServiceException("用户名不符合规定");
        }
        // IP黑名单校验
        String blackStr = Convert.toStr(redisService.getCacheObject(CacheConstants.SYS_LOGIN_BLACKIPLIST));
        if (IpUtils.isMatchedIp(blackStr, IpUtils.getIpAddr())) {
            recordLogService.recordLogininfor(username, LOGIN_FAIL, "很遗憾，访问IP已被列入系统黑名单");
            throw new ServiceException("很遗憾，访问IP已被列入系统黑名单");
        }
        // 查询用户信息
        R<LoginUser> userResult = remoteUserService.getUserInfo(username, SecurityConstants.INNER);

        if (StringUtils.isNull(userResult) || StringUtils.isNull(userResult.getData())) {
            if (!redisService.canSendMessage(username)) throw new ServiceException("账号已锁定,请十分钟后再进行尝试");
            recordLogService.recordLogininfor(username, LOGIN_FAIL, "登录用户不存在");
            throw new ServiceException("登录用户：" + username + " 不存在");
        }

        if (R.FAIL == userResult.getCode()) {
            throw new ServiceException(userResult.getMsg());
        }

        LoginUser userInfo = userResult.getData();
        SysUser user = userResult.getData().getSysUser();
        if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) {
            recordLogService.recordLogininfor(username, LOGIN_FAIL, "对不起，您的账号已被删除");
            throw new ServiceException("对不起，您的账号：" + username + " 已被删除");
        }
        if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
            recordLogService.recordLogininfor(username, LOGIN_FAIL, "用户已停用，请联系管理员");
            throw new ServiceException("对不起，您的账号：" + username + " 已停用");
        }
        passwordService.validate(user, password);
        recordLogService.recordLogininfor(username, LOGIN_SUCCESS, "登录成功");
        return userInfo;
    }

    public void logout(String loginName) {
        recordLogService.recordLogininfor(loginName, LOGOUT, "退出成功");
    }

    /**
     * 注册
     */
    public void register(String username, String password) {
        // 用户名或密码为空 错误
        if (StringUtils.isAnyBlank(username, password)) {
            throw new ServiceException("用户/密码必须填写");
        }
        if (username.length() != UserConstants.USERNAME_MIN_LENGTH) {
            throw new ServiceException("账户长度必须是11位手机号");
        }
        if (!Validator.isMobile(username)) {
            recordLogService.recordLogininfor(username, LOGIN_FAIL, "用户名不在指定范围");
            throw new ServiceException("用户名不符合规定");
        }
        if (password.length() < UserConstants.PASSWORD_MIN_LENGTH || password.length() > UserConstants.PASSWORD_MAX_LENGTH) {
            throw new ServiceException("密码长度必须在5到20个字符之间");
        }
        // 注册用户信息
        SysUser sysUser = new SysUser();
        sysUser.setUserName(username);
        sysUser.setNickName(username);
        sysUser.setPassword(SecurityUtils.encryptPassword(password));
        R<?> registerResult = remoteUserService.registerUserInfo(sysUser, SecurityConstants.INNER);

        if (R.FAIL == registerResult.getCode()) {
            throw new ServiceException(registerResult.getMsg());
        }
        recordLogService.recordLogininfor(username, REGISTER, "注册成功");
    }

    /**
     * 手机登录
     *
     * @param phone   电话
     * @param smsCode 短信代码
     * @return {@link LoginUser}
     */
    public LoginUser mobileLogin(String phone, String smsCode) {
        LoginUser userInfo = validateLogon(phone, smsCode);
        recordLogService.recordLogininfor(phone, LOGIN_SUCCESS, "登录成功");
        return userInfo;
    }

    private LoginUser validateLogon(String phone, String smsCode) {
        if (StringUtils.isAnyBlank(phone, smsCode)) {
            recordLogService.recordLogininfor(phone, LOGIN_FAIL, "手机号/验证码必须填写");
            throw new NotLoginException("缺少必填参数");
        }
        Validator.validateMobile(phone, "手机号格式不正确");

        String code = redisService.getCacheObject(CacheConstants.CAPTCHA_CODE_KEY + phone);
        if (CharSequenceUtil.isBlank(code)) {
            throw new NotLoginException("验证码已过期");
        }
        if (!smsCode.equalsIgnoreCase(code)) {
            throw new NotLoginException("验证码不正确");
        }
        redisService.deleteObject(CacheConstants.CAPTCHA_CODE_KEY + phone);
        R<LoginUser> userResult = remoteUserService.getUserInfoByPhone(phone, SecurityConstants.INNER);
        if (R.FAIL == userResult.getCode() || ObjectUtil.isNull(userResult)) {
            throw new NotLoginException(userResult.getMsg());
        }
        LoginUser userInfo = userResult.getData();
        SysUser user = userResult.getData().getSysUser();
        if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) {
            recordLogService.recordLogininfor(userInfo.getUsername(), LOGIN_FAIL, "对不起，您的账号已被删除");
            throw new NotLoginException("对不起，您的账号：" + phone + " 已被删除");
        }
        if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
            recordLogService.recordLogininfor(userInfo.getUsername(), LOGIN_FAIL, "用户已停用，请联系管理员");
            throw new NotLoginException("对不起，您的账号：" + phone + " 已停用");
        }
        return userInfo;
    }

    /**
     * 发送短信
     *
     * @param phone 电话
     * @return {@link R}<{@link ?}>
     */
    public R<?> sendSms(String phone) {
        String smsKey = CacheConstants.LOGIN_TOKEN_KEY + phone;
        R<LoginUser> userResult = remoteUserService.getUserInfoByPhone(phone, SecurityConstants.INNER);
        if (ObjectUtil.isNull(userResult) || R.FAIL == userResult.getCode()) {
            return R.fail("验证码发送失败!");
        }
        try {
            Object smsKeyObj = redisService.getCacheObject(smsKey);
            if (ObjectUtil.isNotEmpty(smsKeyObj)) return R.fail("点击太快啦,请稍后再试");
            redisService.setCacheObject(smsKey, phone, CacheConstants.SMS_VERIFICATION_TIME);
            // 手机号验证
            if (StringUtils.isEmpty(phone)) {
                return R.fail("手机号不能为空");
            }
            Validator.validateMobile(phone, "手机号格式不正确");
            // 十分钟只允许发送五次短信,避免短信轰炸
            if (!redisService.canSendMessage(phone)) return R.fail("账号已锁定,请十分钟后再进行尝试");
            // 发送短信
            String result = aliYunSmsUtils.sendVerifyCode(phone);

            if (CharSequenceUtil.isBlank(result)) {
                return R.fail("验证码发送失败，请稍后重试");
            }

            redisService.setCacheObject(CacheConstants.CAPTCHA_CODE_KEY + phone, result, CacheConstants.SMS_VERIFICATION_TIME * 3);
            return R.ok("", "短信发送成功,短信有效期三分钟");
        } finally {
            redisService.deleteObject(smsKey);
        }
    }

    /**
     * 重置密码
     *
     * @param phone      电话
     * @param smsCode    短信代码
     * @param password   密码
     * @param rePassword 重新输入密码
     * @return {@link R}<{@link ?}>
     */
    public R<?> resetPassword(String phone, String smsCode, String password, String rePassword) {

        if (CharSequenceUtil.isAllBlank(password, rePassword)) {
            recordLogService.recordLogininfor(phone, LOGIN_FAIL, "密码不能为空");
            throw new ServiceException("请核验输入的密码");
        }
        if (ObjectUtil.notEqual(password, rePassword)) {
            recordLogService.recordLogininfor(phone, LOGIN_FAIL, "两次输入密码不一致");
            throw new ServiceException("两次输入密码不一致");
        }
        // 密码如果不在指定范围内 错误
        if (password.length() < UserConstants.PASSWORD_MIN_LENGTH || password.length() > UserConstants.PASSWORD_MAX_LENGTH) {
            recordLogService.recordLogininfor(phone, LOGIN_FAIL, "用户密码不在指定范围");
            throw new ServiceException("用户密码不在指定范围");
        }
        // 验证
        validateLogon(phone, smsCode);
        // 更新密码
        SysUser sysUser = new SysUser();
        sysUser.setUserName(phone);
        sysUser.setPassword(password);
        R<Boolean> result = remoteUserService.updateUserInfo(sysUser, SecurityConstants.INNER);
        if (result.getCode() == R.SUCCESS) {
            recordLogService.recordLogininfor(phone, LOGIN_SUCCESS, "重置密码成功");
            // 删除该账号的所有缓存
            tokenService.deleteTokens(phone);
            return R.ok("", "重置密码成功");
        }
        recordLogService.recordLogininfor(phone, LOGIN_FAIL, "重置密码失败");
        return R.fail("重置密码失败");
    }

    /**
     * 获取验证码
     *
     * @param captchaBody 用户登录实体类
     * @return 验证码值
     */
    public String getCaptcha(CaptchaBody captchaBody) {
        // 查询用户信息
        R<LoginUser> userResult = remoteUserService.getOperationUserInfoByPhone(captchaBody.getPhone(), SecurityConstants.INNER);
        if (R.FAIL == userResult.getCode()) {
            throw new ServiceException(userResult.getMsg());
        }
        // 检查用户合法性
        this.checkRule(userResult, captchaBody.getPhone());

        // 生成验证码
        String randomCaptcha = createCaptcha.sendCaptcha(captchaBody);
        // 缓存验证码
        this.cacheCaptcha(captchaBody, randomCaptcha);
        return randomCaptcha;
    }

    /**
     * 获取验证码
     *
     * @param captchaBody 用户登录实体类
     * @return 验证码值
     */
    public String getGroupCaptcha(CaptchaBody captchaBody) {
        // 查询用户信息
        R<LoginUser> userResult = remoteUserService.getOperationUserInfoByPhone(captchaBody.getPhone(), SecurityConstants.INNER);
        if (R.FAIL == userResult.getCode()) {
            throw new ServiceException(userResult.getMsg());
        }
        // 检查用户合法性
        this.checkGroupRule(userResult, captchaBody.getPhone());

        // 生成验证码
        String randomCaptcha = createCaptcha.sendCaptcha(captchaBody);
        // 缓存验证码
        this.cacheCaptcha(captchaBody, randomCaptcha);
        return randomCaptcha;
    }

    /**
     * 验证码登录
     *
     * @param loginBody 登录信息
     * @return
     */
    public LoginUser loginCaptcha(LoginBody loginBody) {
        Validator.validateMobile(loginBody.getPhone(), "手机号格式不正确");
        String cacheCaptcha = redisService.getCacheObject(CacheConstants.SMS_LOGIN_CAPTCHA_CODE_KEY + loginBody.getPhone());
        if (StringUtils.isEmpty(cacheCaptcha)) {
            throw new NotLoginException("验证码已过期");
        }
        if (!StringUtils.equals(loginBody.getCaptcha(), cacheCaptcha)) {
            throw new NotLoginException("验证码错误");
        }

        R<LoginUser> userResult = remoteUserService.getOperationUserInfoByPhone(loginBody.getPhone(), SecurityConstants.INNER);
        if (R.FAIL == userResult.getCode()) {
            throw new ServiceException(userResult.getMsg());
        }
        // 检查用户合法性
        this.checkRule(userResult, loginBody.getPhone());

        LoginUser userInfo = userResult.getData();
        recordLogService.recordLogininfor(loginBody.getPhone(), LOGIN_SUCCESS, "登录成功");
        redisService.deleteObject(CacheConstants.SMS_LOGIN_CAPTCHA_CODE_KEY + loginBody.getPhone());

        remoteBrowserLoginService.addBrowserLogin(loginBody.getVisitorId(), SecurityConstants.INNER);
        return userInfo;
    }

    /**
     * 验证码登录
     *
     * @param loginBody 登录信息
     * @return
     */
    public LoginUser loginGroupCaptcha(LoginBody loginBody) {
        Validator.validateMobile(loginBody.getPhone(), "手机号格式不正确");
        String cacheCaptcha = redisService.getCacheObject(CacheConstants.SMS_LOGIN_CAPTCHA_CODE_KEY + loginBody.getPhone());
        if (StringUtils.isEmpty(cacheCaptcha)) {
            throw new NotLoginException("验证码已过期");
        }
        if (!StringUtils.equals(loginBody.getCaptcha(), cacheCaptcha)) {
            throw new NotLoginException("验证码错误");
        }

        R<LoginUser> userResult = remoteUserService.getGroupUserInfoByPhone(loginBody.getPhone(), SecurityConstants.INNER);
        if (R.FAIL == userResult.getCode()) {
            throw new ServiceException(userResult.getMsg());
        }
        // 检查用户合法性
        this.checkGroupRule(userResult, loginBody.getPhone());

        LoginUser userInfo = userResult.getData();
        recordLogService.recordLogininfor(loginBody.getPhone(), LOGIN_SUCCESS, "登录成功");
        redisService.deleteObject(CacheConstants.SMS_LOGIN_CAPTCHA_CODE_KEY + loginBody.getPhone());

        // remoteBrowserLoginService.addBrowserLogin(loginBody.getVisitorId(), SecurityConstants.INNER);
        return userInfo;
    }

    /**
     * 账号密码登录
     *
     * @param phone    手机号
     * @param password 密码
     * @return
     */
    public LoginUser loginPassword(String phone, String password) {
        R<LoginUser> userResult = remoteUserService.getOperationUserInfoByPhone(phone, SecurityConstants.INNER);
        if (R.FAIL == userResult.getCode()) {
            throw new ServiceException(userResult.getMsg());
        }
        // 检查用户合法性
        this.checkRule(userResult, phone);
        LoginUser userInfo = userResult.getData();
        SysUser user = userResult.getData().getSysUser();

        passwordService.validate(user, password);
        recordLogService.recordLogininfor(phone, LOGIN_SUCCESS, "登录成功");
        return userInfo;
    }

    /**
     * 重置密码
     *
     * @param resetPasswordBody 重置密码对象
     */
    public void resetPassword(ResetPasswordBody resetPasswordBody) {
        // 校验验证码是否正确
        Validator.validateMobile(resetPasswordBody.getPhone(), "手机号格式不正确");
        String cacheCaptcha = redisService.getCacheObject(CacheConstants.SMS_RESET_CAPTCHA_CODE_KEY + resetPasswordBody.getPhone());
        if (StringUtils.isEmpty(cacheCaptcha)) {
            throw new NotLoginException("手机号码不正确");
        }
        if (!StringUtils.equals(resetPasswordBody.getCaptcha(), cacheCaptcha)) {
            throw new NotLoginException("验证码错误");
        }

        // 校验两次输入的密码是否一致
        if (!StringUtils.equals(resetPasswordBody.getNewPassword(), resetPasswordBody.getRepeatNewPassword())) {
            throw new NotLoginException("校验两次输入的密码不一致");
        }

        // 获取用户信息
        R<LoginUser> userResult = remoteUserService.getOperationUserInfoByPhone(resetPasswordBody.getPhone(), SecurityConstants.INNER);
        if (R.FAIL == userResult.getCode()) {
            throw new ServiceException(userResult.getMsg());
        }

        // 检查用户合法性
        this.checkRule(userResult, resetPasswordBody.getPhone());


        // 更新密码
        SysUser sysUser = new SysUser();
        sysUser.setUserName(resetPasswordBody.getPhone());
        sysUser.setPassword(resetPasswordBody.getNewPassword());
        R<Boolean> result = remoteUserService.updateUserInfo(sysUser, SecurityConstants.INNER);

        if (result.getCode() != R.SUCCESS) {
            throw new ServiceException("重置密码失败");
        }
        redisService.deleteObject(CacheConstants.SMS_RESET_CAPTCHA_CODE_KEY + resetPasswordBody.getPhone());
        // 删除该账号的所有缓存
        tokenService.deleteTokens(sysUser.getUserName());
    }

    /**
     * 校验是否是运营端用户
     *
     * @return
     */
    private boolean checkUser(Set<String> roles) {
        List<String> roleKey = CollUtil.newArrayList(RoleConstants.CUSTOMER_SERVICE_ROLE_KEY, RoleConstants.INVESTOR_ROLE_KEY);
        List<String> collects = roles.stream().filter(s -> s.endsWith(RoleConstants.CUSTOMER_SERVICE_ROLE_KEY2)).collect(Collectors.toList());
        return CollUtil.containsAny(roles, roleKey) || (!CollectionUtils.isEmpty(collects) && collects.size()>0);
    }

    /**
     * 校验是否是企业用户
     *
     * @return
     */
    private boolean checkGroupUser(Set<String> roles) {
        List<String> roleKey = CollUtil.newArrayList(RoleConstants.ENTERPRISE_ROLE_KEY);
        return CollUtil.containsAny(roles, roleKey);
    }

    /**
     * 校验运营端用户合法性
     *
     * @return
     */
    private boolean checkRule(R<LoginUser> userResult, String phone) {
        if (StringUtils.isNull(userResult) || StringUtils.isNull(userResult.getData())) {
            recordLogService.recordLogininfor(phone, LOGIN_FAIL, "用户不存在");
            throw new ServiceException("用户：" + phone + " 不存在");
        }
        // 校验是否是运营端用户
        if (!this.checkUser(userResult.getData().getRoles())) {
            recordLogService.recordLogininfor(phone, LOGIN_FAIL, "用户无权限");
            throw new ServiceException("用户：" + phone + " 无权限");
        }

        SysUser user = userResult.getData().getSysUser();
        if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) {
            recordLogService.recordLogininfor(phone, LOGIN_FAIL, "对不起，您的账号已被删除");
            throw new ServiceException("对不起，您的账号：" + phone + " 已被删除");
        }
        if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
            recordLogService.recordLogininfor(phone, LOGIN_FAIL, "用户已停用，请联系管理员");
            throw new ServiceException("对不起，您的账号：" + phone + " 已停用");
        }

        return true;
    }

    /**
     * 校验企业用户合法性
     *
     * @return
     */
    private boolean checkGroupRule(R<LoginUser> userResult, String phone) {
        if (StringUtils.isNull(userResult) || StringUtils.isNull(userResult.getData())) {
            recordLogService.recordLogininfor(phone, LOGIN_FAIL, "用户不存在");
            throw new ServiceException("用户：" + phone + " 不存在");
        }
        // 校验是否是企业用户
        if (!this.checkGroupUser(userResult.getData().getRoles())) {
            recordLogService.recordLogininfor(phone, LOGIN_FAIL, "用户不存在");
            throw new ServiceException("用户：" + phone + " 不存在");
        }

        SysUser user = userResult.getData().getSysUser();
        if (UserStatus.DELETED.getCode().equals(user.getDelFlag())) {
            recordLogService.recordLogininfor(phone, LOGIN_FAIL, "对不起，您的账号已被删除");
            throw new ServiceException("对不起，您的账号：" + phone + " 已被删除");
        }
        if (UserStatus.DISABLE.getCode().equals(user.getStatus())) {
            recordLogService.recordLogininfor(phone, LOGIN_FAIL, "用户已停用，请联系管理员");
            throw new ServiceException("对不起，您的账号：" + phone + " 已停用");
        }

        return true;
    }

    /**
     * 缓存验证码
     *
     * @param captchaBody   验证码实体类
     * @param randomCaptcha 验证码随机值
     */
    private void cacheCaptcha(CaptchaBody captchaBody, String randomCaptcha) {
        if (NumberUtil.equals(captchaBody.getType(), CacheConstants.SMS_LOGIN_CAPTCHA_TYPE)) {
            redisService.setCacheObject(CacheConstants.SMS_LOGIN_CAPTCHA_CODE_KEY + captchaBody.getPhone(), randomCaptcha, CacheConstants.SMS_CAPTCHA_TIME, TimeUnit.MINUTES);
        } else if (NumberUtil.equals(captchaBody.getType(), CacheConstants.SMS_RESET_CAPTCHA_TYPE)) {
            redisService.setCacheObject(CacheConstants.SMS_RESET_CAPTCHA_CODE_KEY + captchaBody.getPhone(), randomCaptcha, CacheConstants.SMS_CAPTCHA_TIME, TimeUnit.MINUTES);
        }
    }

    /**
     * 获取用户信息
     */
    public UserVO getUserInfo() {
        SysUser sysUser = SecurityUtils.getLoginUser().getSysUser();
        List<SysRole> rolesInfoList = SecurityUtils.getLoginUser().getRolesInfoList();
        List<SysRoleVO> sysRoleVOS = BeanUtil.copyToList(rolesInfoList, SysRoleVO.class);
        UserVO userVO = new UserVO();
        userVO.setUserId(sysUser.getUserId());
        userVO.setNickName(sysUser.getNickName());
        userVO.setUserName(sysUser.getUserName());
        userVO.setPhoneNumber(sysUser.getPhonenumber());
        userVO.setRoles(sysRoleVOS);
        return userVO;
    }

    /**
     * 判断是否是第一次使用此浏览器登录
     *
     * @param token
     * @return 0:首次，1非首次
     */
    public Integer isFirstBrowserLogin(String token) {
        R<Integer> firstBrowserLogin = remoteBrowserLoginService.isFirstBrowserLogin(token, SecurityConstants.INNER);
        return firstBrowserLogin.getData();
    }

    public R<WxPayUnifiedOrderV3Result.JsapiResult> groupRegister(GroupRegisterBody groupRegisterBody) {
        R<WxPayUnifiedOrderV3Result.JsapiResult> register = remoteGroupService.register(groupRegisterBody, SecurityConstants.INNER);
        return register;
    }

    /**
     * 修改密码
     * @param oldPassword  旧密码
     * @param newPassword  新密码
     */
    public void updatePwd(String oldPassword, String newPassword) throws Exception{
        Long userId = SecurityUtils.getUserId();

        R<LoginUser> userResult = remoteUserService.getOperationUserInfoByUser(userId, SecurityConstants.INNER);
        SysUser user = userResult.getData().getSysUser();

        oldPassword = RsaUtils.decryptByPrivateKey(oldPassword);
        newPassword = RsaUtils.decryptByPrivateKey(newPassword);

        BCryptPasswordEncoder passwordEncoder = new BCryptPasswordEncoder();
        boolean matches = passwordEncoder.matches(oldPassword, user.getPassword());
        if (!matches) {
            throw new ServiceException("旧密码不正确");
        }

        // 更新密码
        SysUser sysUser = new SysUser();
        sysUser.setUserName(user.getPhonenumber());
        sysUser.setPassword(newPassword);
        R<Boolean> result = remoteUserService.updateUserInfo(sysUser, SecurityConstants.INNER);
        if (result.getCode() != R.SUCCESS) {
            throw new ServiceException("重置密码失败");
        }
        redisService.deleteObject(CacheConstants.SMS_RESET_CAPTCHA_CODE_KEY + user.getUserName());
        // 删除该账号的所有缓存
        tokenService.deleteTokens(user.getUserName());

    }



}
